﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace MonoFrameWork
{
    public enum AnimationStatus { NoActive = 0, Active = 1 };

    public class SpriteAnimation: Microsoft.Xna.Framework.DrawableGameComponent
    {
        // Khai báo các biến của lớp

        protected Texture2D spriteStrip;// Đối tượng chứa hình ảnh cần hoạt động

        // cho phép lặp hay không việc vẽ đối tượng
        protected AnimationStatus active;

        // Thông tin của iframe
        protected int fWidth;
        protected int fHeight;
        protected int fCount;
        protected int currentFrame;
        protected int frameTime;
        protected int colum;

        //Các khung vuông bao trùm
        protected Rectangle sourceRect = new Rectangle();
        protected Rectangle destinationRect = new Rectangle();

        // Định nghĩa các vector tọa độ và hình ảnh
        public Vector2 position;
        protected Vector2 velocity;
        protected Color color;
        protected Game game;
        protected SpriteBatch sp;

        // Thông tin thêm
        protected int elapsedTime = 0;// Thời gian qua tính từ lúc bắt đầu
        protected bool looping;
        public bool showBorder=false;
        public int Width
        {
            get { return fWidth; }
        }
        public int Height
        {
            get { return fHeight; }
        }
        public AnimationStatus Active
        {
            get { return active; }
            set { active = value; }
        }
        public Vector2 Velocity
        {
            get { return velocity; }
            set { velocity = value; }
        }
        public void Veclocity(int x, int y)
        {
            velocity.X = x;
            velocity.Y = y;
        }
        public int Colum
        {
            get { return this.colum; }
            set { this.colum = value; }
        }
        public SpriteAnimation(Game game)
            : base(game)
        {
            sp = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
            this.game = game;
            Game.Components.Add(this);
        }
        public SpriteAnimation(Game game, Texture2D texture, Vector2 pos, int frameWidth, int frameHeight, int frameCount, int frameTime,int colum, bool looping)
            : base(game)
        {
            this.color = Color.White;
            this.fWidth = frameWidth;
            this.fHeight = frameHeight;
            this.fCount = frameCount;
            this.frameTime = frameTime;
            this.looping = looping;
            this.spriteStrip = texture;
            elapsedTime = 0;
            currentFrame = 0;
            active = AnimationStatus.Active;

            this.position = pos;
            this.velocity = Vector2.Zero;

            this.colum = colum;
            sourceRect = new Rectangle(currentFrame * fWidth, 0, fWidth, fHeight);

            destinationRect = new Rectangle((int)position.X, (int)position.Y, fWidth, fHeight);
            //sourceRect = new Rectangle(currentFrame * fWidth, 0, fWidth, fHeight);
            //destinationRect = new Rectangle((int)position.X - (int)(fWidth * scaple) / 2,
            //(int)position.Y - (int)(fHeight * scaple) / 2,
            //(int)(fWidth * scaple),
            //(int)(fHeight * scaple));

            sp = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
            this.game = game;
            Game.Components.Add(this);
        }
        public SpriteAnimation(Game game, Texture2D texture, Vector2 pos, int frameWidth, int frameHeight, int frameCount, int frameTime, Color color, bool looping)
            : base(game)
        {
            this.color = color;
            this.fWidth = frameWidth;
            this.fHeight = frameHeight;
            this.fCount = frameCount;
            this.frameTime = frameTime;
            this.looping = looping;
            this.spriteStrip = texture;
            elapsedTime = 0;
            currentFrame = 0;
            active = AnimationStatus.Active;

            this.position = pos;
            this.velocity = Vector2.Zero;

            this.colum = texture.Width / frameWidth;
            sourceRect = new Rectangle(currentFrame * fWidth, 0, fWidth, fHeight);

            destinationRect = new Rectangle((int)position.X, (int)position.Y, fWidth, fHeight);
            //sourceRect = new Rectangle(currentFrame * fWidth, 0, fWidth, fHeight);
            //destinationRect = new Rectangle((int)position.X - (int)(fWidth * scaple) / 2,
            //(int)position.Y - (int)(fHeight * scaple) / 2,
            //(int)(fWidth * scaple),
            //(int)(fHeight * scaple));

            sp = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
            this.game = game;
            Game.Components.Add(this);
        }
        public SpriteAnimation(Game game, Texture2D texture, Vector2 pos, int frameWidth, int frameHeight, int frameCount, int frameTime,int colum, Color color, bool looping)
            : base(game)
        {
            this.color = color;
            this.fWidth = frameWidth;
            this.fHeight = frameHeight;
            this.fCount = frameCount;
            this.frameTime = frameTime;
            this.looping = looping;
            this.spriteStrip = texture;
            elapsedTime = 0;
            currentFrame = 0;
            active = AnimationStatus.Active;

            this.position = pos;
            this.velocity = Vector2.Zero;

            this.colum = colum;
            sourceRect = new Rectangle(currentFrame * fWidth, 0, fWidth, fHeight);

            destinationRect = new Rectangle((int)position.X, (int)position.Y, fWidth, fHeight);
            //sourceRect = new Rectangle(currentFrame * fWidth, 0, fWidth, fHeight);
            //destinationRect = new Rectangle((int)position.X - (int)(fWidth * scaple) / 2,
            //(int)position.Y - (int)(fHeight * scaple) / 2,
            //(int)(fWidth * scaple),
            //(int)(fHeight * scaple));

            sp = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
            this.game = game;
            Game.Components.Add(this);
        }
        public void Initialize(Texture2D texture, Vector2 position, int fWidth, int fHeight, int fCount, int fTimer, Color color, bool looping)
        {
            this.spriteStrip = texture;
            this.position = position;
            this.fWidth = fWidth;
            this.fHeight = fHeight;
            this.fCount = fCount;
            this.frameTime = fTimer;
            this.color = color;
            //this.scaple = scaple;
            this.looping = looping;
            active = AnimationStatus.Active;
            this.colum = texture.Width / fWidth;
            sourceRect = new Rectangle(currentFrame * fWidth, 0, fWidth, fHeight);
            destinationRect = new Rectangle((int)position.X, (int)position.Y, fWidth, fHeight);
        }

        public override void Update(GameTime gameTime)
        {
            if (active == AnimationStatus.NoActive)
                return;
            position += velocity;
            elapsedTime += (int)gameTime.ElapsedGameTime.TotalMilliseconds;
            if (elapsedTime > frameTime)
            {
                currentFrame++;
                if (currentFrame == fCount)
                {
                    currentFrame = 0;
                    if (looping == false)
                        active = AnimationStatus.NoActive;
                }
                elapsedTime = 0;
            }
            int selectedRow = currentFrame / colum;
            int selectedColum = currentFrame % colum;

            sourceRect = new Rectangle(selectedColum * fWidth, selectedRow * fHeight, fWidth, fHeight);

            destinationRect = new Rectangle((int)position.X, (int)position.Y, fWidth, fHeight);

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            if (active == AnimationStatus.Active)
            {
                sp.Begin();

                sp.Draw(spriteStrip, destinationRect, sourceRect, color);

                if (showBorder)
                {
                    sp.Draw(CreateRectangle(fWidth, fHeight, Color.Transparent), new Vector2((int)position.X, (int)position.Y), Color.White);
                }
                sp.End();
            }
            base.Draw(gameTime);
        }
        //Tạo khung hình bao quanh đối tượng sprite
        private Texture2D CreateRectangle(int width, int height, Color colori)
        {
            Texture2D rectangleTexture = new Texture2D(game.GraphicsDevice, fWidth, fHeight, false, SurfaceFormat.Color);// create the rectangle texture, ,but it will have no color! lets fix that
            Color[] color = new Color[fWidth * fHeight];//set the color to the amount of pixels in the textures
            for (int i = 0; i < color.Length; i++)//loop through all the colors setting them to whatever values we want
            {
                if (i < fWidth)
                    color[i] = Color.Red;
                else
                    if ((i % fWidth) <= 0 || (i % fWidth) == fWidth - 1)
                        color[i] = Color.Red;
                    else
                        if (i / fWidth == fHeight - 1)
                            color[i] = Color.Red;
                        else
                            color[i] = colori;
            }
            rectangleTexture.SetData(color);//set the color data on the texture
            return rectangleTexture;//return the texture
        }
        //Vùng bao phủ của texture
        public Rectangle getBound()
        {
            //int X=(int)position.X - (int)(fWidth * scaple) / 2;
            //int Y=(int)position.Y - (int)(fHeight * scaple) / 2;
            //return new Rectangle(X,Y,fWidth,fHeight);
            return new Rectangle((int)position.X, (int)position.Y, fWidth, fHeight);
        }
        public bool CheckCollides(Sprite sprite)
        {
            return this.getBound().Intersects(sprite.getBound());
        }
        public bool CheckCollides(SpriteAnimation sprite)
        {
            return this.getBound().Intersects(sprite.getBound());
        }
        public bool CheckCollides(Animation animation)
        {
            return this.getBound().Intersects(animation.getBound());
        }
        public bool CheckCollides(Texture2D texture,Vector2 position)
        {
            Rectangle rect = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
            return this.getBound().Intersects(rect);
        }
    }
}
